#include <iostream>
#include <string>

//1、函数对象在使用时，可以像普通函数那样调用, 可以有参数，可以有返回值
namespace Test
{
    //1、函数对象在使用时，可以像普通函数那样调用, 可以有参数，可以有返回值
    class MyAdd{
    public :
        int operator()(const int v1, const int v2) const
        {
            return v1 + v2;
        }
    };


    void test01()
    {
        /*
         - 如果 MyAdd 类的 operator() 方法是一个纯函数（即输出仅依赖于输入参数且没有副作用），
         - 那么您可以将 myAdd 声明为 constexpr，这样有助于提高效率，
         - 尤其是在编译时能确定其调用参数的情况下。
         */
        constexpr MyAdd myAdd;
        std::cout << myAdd(10, 10) << std::endl;
    }

    //2、函数对象可以有自己的状态
    class MyPrint
    {
    public:
        MyPrint():count(0){}
        void operator()(const std::string& test)
        {
            std::cout << test << std::endl;
            count++; //统计使用次数
        }

        int count; //内部自己的状态
    };


    void test02()
    {
        MyPrint myPrint;
        myPrint("hello world");
        myPrint("hello world");
        myPrint("hello world");
        std::cout << "myPrint调用次数为： " << myPrint.count << std::endl;
    }


    void doPrint(MyPrint &mp, const std::string &test)
    {
        mp(test);
    }

    // 3.函数对象可以作为参数传递
    void test03()
    {
        MyPrint myPrint;
        doPrint(myPrint, "Hello C++");
    }
}


int main()
{
   // Test::test01();
   // Test::test02();
   Test::test03();
}